package com.nzw.utils;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.*;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by XuZhanSi on 2016/11/29 0029.
 */
public class ReflectUtils {
    static {
        ConvertUtils.register(new Converter() {
            public Object convert(Class type, Object value) {
                if (!(value instanceof String)) {
                    return value;
                }
                String strValue = (String) value;
                if (strValue.trim().equals("")) {
                    return null;
                }
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    return sdf.parse(strValue);
                } catch (ParseException e) {
                    throw new RuntimeException(e);
                }
            }
        }, Date.class);
        ConvertUtils.register(new LongConverter(null), Long.class);
        ConvertUtils.register(new ShortConverter(null), Short.class);
        ConvertUtils.register(new IntegerConverter(null), Integer.class);
        ConvertUtils.register(new DoubleConverter(null), Double.class);
        ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);
    }

    /**
     * 批量复制
     *
     * @param dest  数据源
     * @param clazz 要复制到的类
     * @param <T>
     * @return
     */
    public static <T, P> List<T> batchCopyBeans(List<P> dest, Class<T> clazz) {
        if (dest==null||dest.isEmpty())
            return null;
        List<T> list = new ArrayList<>();
        for (Object object : dest) {
            T entity = null;
            try {
                entity = clazz.newInstance();
                BeanUtils.copyProperties(entity, object);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            list.add(entity);
        }
        return list;
    }

    /**
     * @param dest 没数据的
     * @param orig 有数据的
     */
    public static void copyBean(Object dest, Object orig) {
        try {
            BeanUtils.copyProperties(dest, orig);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    /**
     * 复制bean
     * @param entity
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T copyBean(Object entity,Class<T> clazz){
        T t = null;
        try {
            t = clazz.newInstance();
            BeanUtils.copyProperties(t, entity);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * map转实体
     *
     * @param dest
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBeanByMap(Map<String, Object> dest, Class<T> clazz) {
        T t = null;
        try {
            t = clazz.newInstance();
            BeanUtils.copyProperties(t, dest);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 从bean里获取属性值封装到map，跳过为null值的属性
     *
     * @return
     */
    public static Map<String, Object> getAvaliblePropertyFromBean(Object entity) {
        if (entity == null)
            return null;
        Map<String, Object> parmas = new HashMap<>();
        Class clazz = entity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            if (!"serialVersionUID".equals(name)){//序列号不用取
                String getMethodName = "get" + StringUtil.firstUpperCase(name);
                try {
                    Method method = clazz.getMethod(getMethodName);
                    Object val=method.invoke(entity);
                    if(val!=null){
                        parmas.put(name,val);
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return parmas;
    }


}
